//
//  AQClassInfo.h
//  Runtime
//
//  Created by jikuan zhang on 2022/6/8.
//  Copyright © 2022 hsgd. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

NS_ASSUME_NONNULL_BEGIN
/**
 Type encoding's type.
 */
typedef NS_OPTIONS(NSUInteger, AQEncodingType) {
    AQEncodingTypeMask       = 0xFF, /// < mask of type value
    AQEncodingTypeUnknown    = 0, /// < unknow
    AQEncodingTypeVoid       = 1, /// < void
    AQEncodingTypeBool       = 2, ///< bool
    AQEncodingTypeInt8       = 3, ///< char / BOOL
    AQEncodingTypeUInt8      = 4, ///< unsigned char
    AQEncodingTypeInt16      = 5, ///< short
    AQEncodingTypeUInt16     = 6, ///< unsigned short
    AQEncodingTypeInt32      = 7, ///< int
    AQEncodingTypeUInt32     = 8, ///< unsigned int
    AQEncodingTypeInt64      = 9, ///< long long
    AQEncodingTypeUInt64     = 10, ///< unsigned long long
    AQEncodingTypeFloat      = 11, ///< float
    AQEncodingTypeDouble     = 12, ///< double
    AQEncodingTypeLongDouble = 13, ///< long double
    AQEncodingTypeObject     = 14, ///< id
    AQEncodingTypeClass      = 15, ///< Class
    AQEncodingTypeSEL        = 16, ///< SEL
    AQEncodingTypeBlock      = 17, ///< block
    AQEncodingTypePointer    = 18, ///< void*
    AQEncodingTypeStruct     = 19, ///< struct
    AQEncodingTypeUnion      = 20, ///< union
    AQEncodingTypeCString    = 21, ///< char*
    AQEncodingTypeCArray     = 22, ///< char[10] (for example)
    
    AQEncodingTypeQualifierMask   = 0xFF00,   ///< mask of qualifier
    AQEncodingTypeQualifierConst  = 1 << 8,  ///< const
    AQEncodingTypeQualifierIn     = 1 << 9,  ///< in
    AQEncodingTypeQualifierInout  = 1 << 10, ///< inout
    AQEncodingTypeQualifierOut    = 1 << 11, ///< out
    AQEncodingTypeQualifierBycopy = 1 << 12, ///< bycopy
    AQEncodingTypeQualifierByref  = 1 << 13, ///< byref
    AQEncodingTypeQualifierOneway = 1 << 14, ///< oneway
    
    AQEncodingTypePropertyMask         = 0xFF0000, ///< mask of property
    AQEncodingTypePropertyReadonly     = 1 << 16, ///< readonly
    AQEncodingTypePropertyCopy         = 1 << 17, ///< copy
    AQEncodingTypePropertyRetain       = 1 << 18, ///< retain
    AQEncodingTypePropertyNonatomic    = 1 << 19, ///< nonatomic
    AQEncodingTypePropertyWeak         = 1 << 20, ///< weak
    AQEncodingTypePropertyCustomGetter = 1 << 21, ///< getter=
    AQEncodingTypePropertyCustomSetter = 1 << 22, ///< setter=
    AQEncodingTypePropertyDynamic      = 1 << 23, ///< @dynamic
};

AQEncodingType AQEncodingGetType(const char *typeEncoding);

@interface AQClassIvarInfo : NSObject
@property (nonatomic, assign, readonly) Ivar ivar;              ///< ivar opaque struct
@property (nonatomic, strong, readonly) NSString *name;         ///< Ivar's name
@property (nonatomic, assign, readonly) ptrdiff_t offset;       ///< Ivar's offset
@property (nonatomic, strong, readonly) NSString *typeEncoding; ///< Ivar's type encoding
@property (nonatomic, assign, readonly) AQEncodingType type;    ///< Ivar's type

/**
 Creates and returns an ivar info object.
 
 @param ivar ivar opaque struct
 @return A new object, or nil if an error occurs.
 */
- (instancetype)initWithIvar:(Ivar)ivar;
@end

@interface AQClassInfo : NSObject

@end

NS_ASSUME_NONNULL_END
